Skip to content

Fix keep_max_files re-download churn by suppressing pruned entries - #1487

Open
michaeldyrynda wants to merge 2 commits into
jmbannon:masterfrom
michaeldyrynda:master
Open

Fix keep_max_files re-download churn by suppressing pruned entries#1487
michaeldyrynda wants to merge 2 commits into
jmbannon:masterfrom
michaeldyrynda:master

Conversation

@michaeldyrynda

Copy link
Copy Markdown
Contributor

Summary

Follow-up to #1484 / #1461.

Entries pruned by keep_max_files were fully removed from the download archive, causing yt-dlp to re-download them on every run - only for them to be immediately pruned again in an endless cycle.

This fix introduces a suppressed flag on pruned entries: files are deleted from disk, but the entry ID stays in the download archive so yt-dlp knows not to re-download it.

Changes

  • Adds suppressed flag on DownloadMapping - backward-compatible serialisation (old archives without the field default to False)
  • suppress_entry() / _suppress_entry() - clears file names and marks the entry as suppressed, keeping it in the archive
  • remove_stale_files() - uses _suppress_entry for keep_max_files pruning (date-range pruning still fully removes entries, since yt-dlp's own date filter prevents re-download)
  • add_entry() - unsuppresses if a previously-suppressed entry gets re-downloaded
  • Counting fix - suppressed entries are filtered out before keep_max_files counting so they don't consume slots

Tests

  • Updated existing keep_max_files sort tests to verify both active and suppressed entry sets
  • Added TestDownloadMappingSuppressed for serialisation roundtrip
  • Added TestSuppressedEntriesPreventRedownload covering: archive inclusion, slot counting, file deletion, and JSON roundtrip

…ad archive

Entries pruned by keep_max_files were fully removed from the download
archive, causing yt-dlp to re-download them on every run. Now pruned
entries are marked as suppressed — files are deleted but the entry ID
stays in the archive to prevent re-download churn.

- Add suppressed flag to DownloadMapping with backward-compatible serialization
- Add suppress_entry/unsuppress paths in DownloadMappings
- Use _suppress_entry for keep_max_files pruning, _remove_entry for date_range
- Filter suppressed entries from keep_max_files counting loop
@jmbannon

Copy link
Copy Markdown
Owner

Another solution to consider is, if a playlist-based sort is used, we could add a playlist_index parameter under the hood. I.e., keep_max is 20, using a playlist idx ascending, we could pass 0:20 to only look at that subset of videos.

I think that could be more clean than wrangling the archive more. Its also midnight and Im in bed lol, will need to think about this a bit more. I do appreciate the quick follow-up!

@michaeldyrynda

Copy link
Copy Markdown
Contributor Author

That does make sense. I'll let you think a bit more on how you want it implemented and I can take another crack.

All good on the quick follow, i've been downloading the same 50 videos for a few days since the update so it's driving me nuts in the meantime ha

@jmbannon

jmbannon commented Jul 21, 2026

Copy link
Copy Markdown
Owner

In your setup, you should try passing:

ytdl_options:
          playlist_items: ":20"

or -20: if it sorts descending.

assuming max to keep is 20, and see if that solves things

@michaeldyrynda

Copy link
Copy Markdown
Contributor Author

Alright, i think that worked.

Added a new preset to config.yaml then used it in subscriptions.yaml and seems to have done what it was meant to 🥳

# config.yaml
presets:
    "Last N Playlist Items":
      ytdl_options:
        playlist_items: "-{only_recent_max_files}:"

# subscriptions.yaml
'Plex TV Show by Date | Only Recent | Last N Playlist Items':
    '= Tech':
      '~AI that works':
        url: 'https://www.youtube.com/playlist?list=PLi60mUelRAbFqfgymVfZttlkIyt0XHZjt'
        only_recent_max_files: 50

Only caveat this way is needing to create two presets if you wanted to grab the First N Playlist Items - but that becomes config, rather than code change anyway.

@jmbannon

Copy link
Copy Markdown
Owner

This line is where we can inject ytdl_option args based on output options: https://github.com/jmbannon/ytdl-sub/blob/master/src/ytdl_sub/subscriptions/subscription_ytdl_options.py#L97

Based on the sort, we can pass the appropriate value.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants